// Copyright (C) 2009 Jesse Jones
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using MmmDoc;
using Mono.Cecil;
using System;

namespace MmmDoc.Database
{
	/// <summary>A method, field, event etc of a type.</summary>
	internal abstract class Member : CodeElement
	{
		protected Member(TypeDef type, string fullName) : base(fullName)
		{
			DeclaringType = type;
		}
		
		public string[] CustomAttributes {get; protected set;}
		
		/// <summary>The type the member is declared within.</summary>
		public TypeDef DeclaringType {get; protected set;}
		
		/// <summary>Used for table of contents.</summary>
		public string Key {get; protected set;}
		
		public MemberAccess Access {get; protected set;}
		
		/// <summary>Keywords like public, new, virtual, etc.</summary>
		public string Modifiers {get; protected set;}
		
		/// <summary>Based on the name of the member.</summary>
		/// <remarks>May include generic parameters.</remarks>
		public string Name {get; protected set;}
		
		internal abstract string GetXmlName(TypeDef type);
		
		internal virtual void Disambiguate()
		{
		}
		
		internal abstract SortKey GetSortKey();
		
		#region Internal Types
		/// <summary>Used to sort members.</summary>
		internal sealed class SortKey
		{
			public SortKey()
			{
				Weight = 10;
				SubWeight = 0;
			}
			
			/// <summary>Primary key.</summary>
			/// <remarks>Defaults to 10.</remarks>
			public int Weight {get; set;}
			
			/// <summary>Secondary key.</summary>
			public string Name {get; set;}
			
			/// <summary>Tertiary key.</summary>
			/// <remarks>Defaults to 0.</remarks>
			public int SubWeight {get; set;}
			
			public int CompareTo(SortKey rhs)
			{
				int result = 0;
				
				if (result == 0)
					result = Weight.CompareTo(rhs.Weight);
				
				if (result == 0)
					result = Name.CompareTo(rhs.Name);
				
				if (result == 0)
					result = SubWeight.CompareTo(rhs.SubWeight);
				
				return result;
			}
		}
		#endregion
	}
}
